package com.ruoyi.common.utils.media;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import net.coobird.thumbnailator.Thumbnails;
import java.io.*;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * @author xumh
 * @title: ImageUtil
 * @projectName ruoyi
 * @description: TODO
 * @date 2024/12/1215:51
 */
public class ImageUtil {
    public ImageUtil() {
    }

    /**
     * 将BufferedImage对象写入文件
     * @param bufferedImage
     * @param outPath
     * @throws IOException
     */
    public static void writeBufferedImageToFile(BufferedImage bufferedImage, String outPath) throws IOException{
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "jpg", outputStream);
        byte[] imageBytes = outputStream.toByteArray();
        // 使用 imageBytes 作为输出，例如可以将其写入文件或者进行其他处理
        FileOutputStream fileOutputStream = new FileOutputStream(outPath);
        fileOutputStream.write(imageBytes);
        fileOutputStream.close();
        outputStream.close();
    }
    
    /**
     * 待合并的两张图必须满足这样的前提，如果水平方向合并，则高度必须相等；如果是垂直方向合并，宽度必须相等。
     * mergeImage方法不做判断，自己判断。
     * @param inputStream1 待合并的第一张图
     * @param inputStream2 带合并的第二张图
     * @param isHorizontal 为true时表示水平方向合并，为false时表示垂直方向合并
     * @return 返回合并后的BufferedImage对象
     * @throws IOException
     */
    public static BufferedImage mergeImage(InputStream inputStream1,InputStream inputStream2, boolean isHorizontal) throws IOException {
        BufferedImage img1 = ImageIO.read(inputStream1);
        if (img1 == null){
            throw new IOException("第一张图：无法读取文件，可能是格式不支持或文件损坏");
        }
        BufferedImage img2 = ImageIO.read(inputStream2);
        if (img2 == null){
            throw new IOException("第二张图：无法读取文件，可能是格式不支持或文件损坏");
        }
        int w1 = img1.getWidth();
        int h1 = img1.getHeight();
        int w2 = img2.getWidth();
        int h2 = img2.getHeight();

        // 从图片中读取RGB
        int[] ImageArrayOne = new int[w1 * h1];
        ImageArrayOne = img1.getRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 逐行扫描图像中各个像素的RGB到数组中
        int[] ImageArrayTwo = new int[w2 * h2];
        ImageArrayTwo = img2.getRGB(0, 0, w2, h2, ImageArrayTwo, 0, w2);

        // 生成新图片
        BufferedImage DestImage = null;
        if (isHorizontal) { // 水平方向合并
            DestImage = new BufferedImage(w1+w2, h1, BufferedImage.TYPE_INT_RGB);
            DestImage.setRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 设置上半部分或左半部分的RGB
            DestImage.setRGB(w1, 0, w2, h2, ImageArrayTwo, 0, w2);
        } else { // 垂直方向合并
            DestImage = new BufferedImage(w1, h1 + h2, BufferedImage.TYPE_INT_RGB);
            DestImage.setRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 设置上半部分或左半部分的RGB
            DestImage.setRGB(0, h1, w2, h2, ImageArrayTwo, 0, w2); // 设置下半部分的RGB
        }

        return DestImage;
    }

    /**
     * 给图片上添加文字
     * @param text 文字
     * @param inputStream 图片
     * @param outputPath 图片保存位置
     * @throws IOException
     */
    public static void addTextToImage(String text,InputStream inputStream, String outputPath) throws IOException {
        BufferedImage srcImage = ImageIO.read(inputStream);
        if (srcImage == null){
            throw new IOException("无法读取文件，可能是格式不支持或文件损坏");
        }
        int imageWidth = srcImage.getWidth();
        int imageHeight = srcImage.getHeight();

        BufferedImage outputImage = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = outputImage.createGraphics();

        // 绘制原图
        g2d.drawImage(srcImage, 0, 0, null);

        // 设置画笔
        g2d.setColor(Color.BLACK);
        g2d.setFont(new Font("宋体", Font.BOLD, 20));

        // 设置文字位置
        FontMetrics fontMetrics = g2d.getFontMetrics();
        Rectangle2D rect = fontMetrics.getStringBounds(text, g2d);
        double textWidth = rect.getWidth();
        double textHeight = rect.getHeight();

        // 在图片上绘制文字
        // 参数分别为文字，x坐标，y坐标
        g2d.drawString(text,150, 150);

        // 释放画笔
        g2d.dispose();

        // 输出图片
        ImageIO.write(outputImage, "jpg", new File(outputPath));
    }

    public static String ImageToBase64(String imgFilePath) {
        byte[] data = null;

        try {
            InputStream in = new FileInputStream(imgFilePath);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException var3) {
            var3.printStackTrace();
        }

        return Base64.encodeBase64String(data);
    }

    public static boolean Base64ToImage(String imgBase64, String imgFilePath) {
        if (imgBase64 == null) {
            return false;
        } else {
            try {
                byte[] bytes = Base64.decodeBase64(imgBase64);

                for(int i = 0; i < bytes.length; ++i) {
                    if (bytes[i] < 0) {
                        bytes[i] = (byte)(bytes[i] + 256);
                    }
                }

                OutputStream out = new FileOutputStream(imgFilePath);
                out.write(bytes);
                out.flush();
                out.close();
                return true;
            } catch (Exception var4) {
                return false;
            }
        }
    }

    public static Map<String, Object> getImgHeightAndWidth(InputStream is) {
        BufferedImage src = null;
        Map<String, Object> ret = new HashMap();
        ret.put("w", -1);
        ret.put("h", -1);

        try {
            src = ImageIO.read(is);
            ret.put("w", src.getWidth((ImageObserver)null));
            ret.put("h", src.getHeight((ImageObserver)null));
            is.close();
        } catch (Exception var4) {
            var4.printStackTrace();
        }

        return ret;
    }

    public static String commpress(String srcPath, String desPath, long desFileSize, double accuracy) {
        if (!StringUtils.isEmpty(srcPath) && !StringUtils.isEmpty(srcPath)) {
            if (!(new File(srcPath)).exists()) {
                return null;
            } else {
                try {
                    Thumbnails.of(new String[]{srcPath}).scale(1.0D).toFile(desPath);
                    commpressCycle(desPath, desFileSize, accuracy);
                    return desPath;
                } catch (Exception var7) {
                    var7.printStackTrace();
                    return null;
                }
            }
        } else {
            return null;
        }
    }

    public static void commpressCycle(String desPath, long desFileSize, double accuracy) throws IOException {
        File srcFileJPG = new File(desPath);
        long srcFileSizeJPG = srcFileJPG.length();
        if (srcFileSizeJPG > desFileSize * 1024L) {
            BufferedImage bim = ImageIO.read(srcFileJPG);
            int srcWdith = bim.getWidth();
            int srcHeigth = bim.getHeight();
            int desWidth = (new BigDecimal(srcWdith)).multiply(new BigDecimal(accuracy)).intValue();
            int desHeight = (new BigDecimal(srcHeigth)).multiply(new BigDecimal(accuracy)).intValue();
            Thumbnails.of(new String[]{desPath}).size(desWidth, desHeight).outputQuality(accuracy).toFile(desPath);
            commpressCycle(desPath, desFileSize, accuracy);
        }
    }
}
